#include <iostream>

/*

所谓的完美转发，是指std::forward会将输入的参数原封不动地传递到下一个函数中，这个“原封不动”指的是，如果输入的参数是左值，那么传递给下一个函数的参数的也是左值；如果输入的参数是右值，那么传递给下一个函数的参数的也是右值。


完美转发使用两步来完成任务：

1. 在模板中使用&&接收参数。
2. 使用std::forward()转发给被调函数.

这样左值作为仍旧作为左值传递，右值仍旧作为右值传递！
------------------

std::move是将对象的状态或者所有权从一个对象转移到另一个对象，只是转移，没有内存的搬迁或者内存拷贝。
*/
class CData
{
public:
	CData() = delete;
	CData(const char *ch) : data(ch)
	{
		std::cout << "CData(const char* ch)" << std::endl;
	}
	CData(const std::string &str) : data(str)
	{
		std::cout << "CData(const std::string& str)" << std::endl;
	}
	CData(std::string &&str) : data(str)
	{
		std::cout << "CData(std::string&& str)" << std::endl;
	}
	~CData()
	{
		std::cout << "~CData()" << std::endl;
	}

private:
	std::string data;
};

template <typename T>
CData *Creator_forward(T &&t)
{
	return new CData(std::forward<T>(t));
}

template <typename T>
CData *Creator(T &&t)
{
	/*
	  t 是一个变量，为左值，无论左值引用类型的变量还是右值引用类型的变量，都是左值，因为它们有名字。例如可以写如下代码：

   int a = 100;
   int&& b = 100;
   int& c = b; //正确，b为左值
   int& d = 100; //错误
	 */
	return new CData(t);
}

void Forward()
{
	const char *value = "hello";
	std::string str1 = "hello";
	std::string str2 = " world";
	CData *p = Creator(str1 + str2);
	delete p;
	CData *p2 = Creator_forward(str1 + str2);
	delete p2;
	// output:
	// 	CData(const std::string& str)
	// ~CData()
	// CData(std::string&& str)
	// ~CData()
}

int main()
{
	int a = 100;
	int &&b = 100;
	int &c = b; // 正确，b为左值
	// int& d = 100; //错误
	Forward();
}
